#!/usr/bin/env python
# -*- coding:utf-8 -*-

#reload system then set default encoding to utf8
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import os.path
import re
import pymongo
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from sphinxapi import *

import pprint

pp = pprint.PrettyPrinter()

from tornado.options import define, options

define("port", default=8088, help="Search Engine Port", type=int)

class Application(tornado.web.Application):
    def __init__(self):
        self.init_handler()
        self.init_setting()
        tornado.web.Application.__init__(self, self.handlers, **self.settings)
        self.init_database()
        self.init_sphinx()

    def __del__(self):
        self.connection.disconnect()
        #self.db.close()

    def init_handler(self):
        self.handlers = [
             (r"/", MainHandler),
             (r"/words", Autocomplete_Handler),
             (r"/search_pattern", SearchresultHandler),
             (r"/detail/([0-9]+)",Detail_Handler),
        ]

    def init_setting(self):
        self.settings = dict(
            application_title=u"新闻搜索引擎".encode('utf-8'),
            template_path=os.path.join(os.path.dirname(__file__), "templates"),
            static_path=os.path.join(os.path.dirname(__file__), "static"),
            ui_modules={"List": ListModule},
            debug=True,
            gzip=True,
        )

    def init_database(self):
        self.connection = pymongo.Connection('10.120.30.238', 27017)
        self.db = self.connection.news

    def init_sphinx(self):
        self.cl = SphinxClient()
        self.cl.SetServer ( '10.120.30.238', 9312 )
        self.cl.SetWeights ( [100, 1] )
        self.cl.SetMatchMode ( SPH_MATCH_EXTENDED2 )
        #self.cl.SetLimits ( 0, 1000, max(1000,1000) )

class BaseHandler(tornado.web.RequestHandler):
    def sphinx_object(self):
        return self.application.cl

    def mongodb_object(self):
        return self.application.db
    
class MainHandler(BaseHandler):
    def get(self):
        self.render("main.html")

class SearchresultHandler(BaseHandler):
    def get(self):
        entry = dict()
        search_pattern = self.get_argument("search_pattern",None)
        #pageno = self.get_argument("page_no",None)
        #if pageno==None:
        #   pageno=0
        if search_pattern == None:
           self.render("main.html")
        ids = self._sphinx_search(search_pattern)
        #datasets = self._search_list(ids,pageno)
        entry["search_pattern"] = search_pattern
        #entry["pageno"] = pageno
        if ids:
          datasets = self._search_list(ids)
          entry["data"] = datasets
          entry["totalno"] = len(datasets)
          #pprint.PrettyPrinter().pprint(entry)
        else:
          entry["no_results"] = 1
        self.render("lists.html", entries=entry)

    def post(self):
        self.render("main.html")

    def _sphinx_search(self,search_pattern):
        self.sphinx_object().SetLimits ( 0, 1000, max(1000,1000) )
        res = self.sphinx_object().Query(search_pattern,'news')
        pprint.PrettyPrinter().pprint(res)
        if res.has_key("matches") and res["matches"] is not []:
           ids = [match['id'] for match in res["matches"]]
           return ids
        else:
           return False

#    def _search_list(self,ids,offset):
    def _search_list(self,ids):
        #start_offset = (19*offset)
        #end_offset = (19*offset) + 19

        #query = [{'id':id} for id in ids[start_offset:end_offset]]
        query = [{'id':id} for id in ids]
        #print query
        res = self.mongodb_object().news.find({ "$or":query })
        res = [result for result in res]
        #pprint.PrettyPrinter().pprint(res)
        return res

class Detail_Handler(BaseHandler):
    def get(self, dt_id):
        #print type(int(dt_id))
        if dt_id:
           entry = self._get_detail(int(dt_id))
           self.render("detail.html", entry=entry)
        else:
           self.render("detail.html", entry=entry)

    def _get_detail(self, dt_id):
        entry = self.mongodb_object().news.find_one({"id":dt_id})
        #pprint.PrettyPrinter().pprint(entry)
        return entry

class Autocomplete_Handler(BaseHandler):
    def get(self):
        autocomplete_words = self.get_argument("term",None)
        ids = self._sphinx_search(autocomplete_words)
        self.set_header("Content-Type","application/json")
        if ids:
            datasets = self._search_list(ids)
            pp.pprint(datasets)
            self.write(tornado.escape.json_encode(datasets))
        else:
            self.write('[]')
        #pp.pprint(datasets)
        #pp.pprint(tornado.escape.json_encode(datasets))
    def _sphinx_search(self,words):
        self.sphinx_object().SetLimits ( 0, 10, max(10,10) )
        res = self.sphinx_object().Query("^%s" % words,'autocomplete')
        #pprint.PrettyPrinter().pprint(res)
        if res.has_key("matches") and res["matches"] is not []:
           ids = [match['id'] for match in res["matches"]]
           return ids
        else:
           return False
    def _search_list(self,ids):
        query = [{'id':id} for id in ids]
        #print query
        res = self.mongodb_object().autocomplete_kw.find({ "$or":query },{'_id':False}).sort('hits',pymongo.DESCENDING)
        res = [{'id':str(result['id']),'label':result['words'],'value':result['words']} for result in res]
        #pprint.PrettyPrinter().pprint(res)
        return res

class ListModule(tornado.web.UIModule):
    def css_files(self):
        return "css/master.css"
    def render(self,entry):
        return self.render_string("modules/list.html", entry=entry)

#server part
def main():
    tornado.options.parse_command_line()
    http_server = tornado.httpserver.HTTPServer(Application())
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()
